/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package eu.anorien.dmo.gui.optimization;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Stroke;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import org.apache.log4j.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.general.SeriesChangeEvent;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 *
 * @author David Miguel Antunes <davidmiguel [ at ] antunes.net>
 */
public class PerformanceGraph extends JPanel {

    private static final Logger logger = Logger.getLogger(PerformanceGraph.class);
    private final Color[] colors = new Color[]{
        Color.GREEN.brighter(),
        Color.RED.darker(),};
    private final Stroke[] strokes = new Stroke[]{
        new BasicStroke(4f),
        new BasicStroke(3f),};
    private XYSeries performance = new XYSeries("Best Performance (1/error)");
    private XYSeries results = new XYSeries("Results (1/error)");
    private XYSeriesCollection dataset = new XYSeriesCollection();
    private JFreeChart chart;
    private ChartPanel panel;

    public PerformanceGraph() {
        this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
        dataset.addSeries(performance);
        dataset.addSeries(results);

        chart = ChartFactory.createXYLineChart("Performance", "Time (min)", "Performance (1/error)", dataset, PlotOrientation.VERTICAL, true, true, true);

        final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
        renderer.setSeriesShapesVisible(0, false);
        renderer.setSeriesLinesVisible(1, false);
        chart.getXYPlot().setRenderer(renderer);

        XYPlot plot = chart.getXYPlot();
        for (int i = 0; i < colors.length; i++) {
            plot.getRenderer().setSeriesPaint(i, colors[i]);
            plot.getRenderer().setSeriesStroke(i, strokes[i]);
        }

        panel = new ChartPanel(chart);
        PerformanceGraph.this.add(panel);
    }

    synchronized void newRun(final long runTime, final double error) {

        double min = (double) runTime / (1000.0 * 60.0);
        results.add(min, 1 / error);
        if (results.getItemCount() > 500) {
            results.remove(0);
        }
        updateGraph();
    }

    synchronized void newSmallestError(final long runTime, final double smallestError) {

        double min = (double) runTime / (1000.0 * 60.0);
        performance.add(min, 1 / smallestError);
        updateGraph();
    }

    private void updateGraph() {
        try {
            EventQueue.invokeLater(new Runnable() {

                public void run() {
                    EventQueue.invokeLater(new Runnable() {

                        public void run() {
                            synchronized (PerformanceGraph.this) {
                                dataset.seriesChanged(new SeriesChangeEvent(this));
                            }
                            PerformanceGraph.this.validate();
                        }
                    });
                }
            });
        } catch (Exception ex) {
            logger.error(ex);
        }
    }
}
